#pragma once

#include"Log.hpp"

#include<iostream>
#include<string>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include"CopySocket.hpp"
#include<functional>

using namespace LogMoudle;

#define SOC(v) (sockaddr*)(v)


//const static std::string default_ip="127.0.0.1";
const static uint16_t default_port=8888;

const static int default_size=1024;

using func_t=std::function<void(const std::string &key,std::string *response)>;


class Udpserver{

public:
//缺省参数要放到后面
Udpserver(func_t func,uint16_t port=default_port):_port(port),_func(func)
{

}

void Init()
{
    //创建socket
    _sockfd=socket(AF_INET,SOCK_DGRAM,0);
    if(_sockfd==-1)
    {
        LOG(Logevel::FATAL)<<"socket creat is error";
        exit(1);
    }

    LOG(Logevel::INFO)<<"socket creat success";

    //绑定套接字，指定网络信息

    struct sockaddr_in local;
    bzero(&local,sizeof(local));
    local.sin_family=AF_INET;
    local.sin_port=htons(_port);

    //接收来自任意服务器的请求

    local.sin_addr.s_addr=INADDR_ANY;
    int n=bind(_sockfd,SOC(&local),sizeof(local));

    if(n!=0)
    {
        LOG(Logevel::FATAL)<<"bind is error";
        exit(2);
    }


}

void Start()
{
    //存储发过来的信息
    char buffer[default_size];
    //服务器永不退出
    while(true)
    {
        struct sockaddr_in peer;
        socklen_t len=sizeof(peer);
        bzero(&peer,sizeof(peer));
        ssize_t n=recvfrom(_sockfd,buffer,sizeof(buffer)-1,0,SOC(&peer),&len);

        if(n>0)
        {
            //后面进行封装
            buffer[n]=0;

            CopySocket cpeeer(peer);
            //std::string ip=inet_ntoa(peer.sin_addr);
            //uint16_t port=ntohs(peer.sin_port);
            //std::cout<<"["<<ip<<":"<<port<<"]#"<<buffer<<std::endl;
            std::cout<<"["<<cpeeer.PrintDebug()<<"]#"<<buffer<<std::endl;
            //回显到客户端
            std::string value;
            _func(buffer,&value);
            sendto(_sockfd,value.c_str(),value.size(),0,SOC(&peer),len);

        }
    }
}

~Udpserver()
{

}

private:
        std::string _ip;
        uint16_t _port;
        int _sockfd;
        func_t _func;
};